﻿module Sustainalytics.Authentication {

    export interface ngScope extends ng.IScope {
        changePasswordForm: any;
    }


    export class AccountController {

        public usercredentials: UserCredentials;
        public loginForm: any;
        //public error: string;
        public changePasswordForm: any;
        public $$autocomplete: any;
        public redirectTo: string;
        public err: string;

        constructor(
            private $q: ng.IQService,
            private $timeout: ng.ITimeoutService,
            private $scope: ngScope,
            private $routeParams: ng.route.IRouteParamsService,
            private $location: ng.ILocationService,
            private $rootScope,
            private AuthenticationService: IAuthenticationService,
            private notificationFactory: Common.INotificationFactory,
            private staticObjects: Common.IStaticObjects,
            private UserInfoService: IUserInfoService) {

            var ctx = this;

            $scope['auth'] = this;

            ctx.redirectTo = ctx.$routeParams['redirectTo'];

            ctx.initRouteError();

            if ($routeParams != undefined && $routeParams['tempKey'] != undefined && $routeParams['user'] != undefined) {
                $.when(ctx.init());
            }

            $scope.$watch('usercredentials.username', () => {
                if (!this.usercredentials)
                    return;

                if (this.usercredentials.autoComplete)
                    this.usercredentials.errorMessage = "";

                if (this.usercredentials.autoComplete) {
                    this.usercredentials.autoComplete = this.usercredentials.autoComplete - 1;
                }
            });

            $scope.$watch('usercredentials.password', () => {

                if (!this.usercredentials)
                    return;

                if (!this.usercredentials.autoComplete)
                    this.usercredentials.errorMessage = "";

                if (this.usercredentials.autoComplete) {
                    this.usercredentials.autoComplete = this.usercredentials.autoComplete - 1;
                }
            });
        }

        private initRouteError() {
            var ctx = this;

            var errCodeStr = ctx.$routeParams['err'];

            if (!errCodeStr)
                return;

            var errCode = parseInt(errCodeStr);

            if (!errCode)
                return;

            if (!ctx.usercredentials) {
                ctx.usercredentials = { errorMessage: null, password: '', username: ctx.$routeParams['user'], confirmPassword: '', forgotPasswordEmail: '', rememberMe: true, autoComplete: null };
            }

            ctx.err = ctx.staticObjects.getMessageByInternalCode(errCode);
        }

        private init() {
            var ctx = this;

            ctx.usercredentials = { errorMessage: null, password: '', username: ctx.$routeParams['user'], confirmPassword: '', forgotPasswordEmail: '', rememberMe: true, autoComplete: null };

            var loginParams = "grant_type=password" +
                "&username=" + ctx.$routeParams['user'] +
                "&password=" + ctx.$routeParams['tempKey'] +
                "&client_id=clientId1" +
                "&client_secret=secret1";

            ctx.AuthenticationService.login(loginParams)
                .success((authData: AuthData) => {
                    if (!authData.access_token || !authData.expires_in || !authData.refresh_token) {
                        ctx.notificationFactory.error("", "Login failed!");
                    }
                    else {
                        ctx.usercredentials.errorMessage = "";
                        authData.loginTime = new Date();
                        ctx.$rootScope.authData = authData;
                        var refreshToken = { refreshToken: authData.refresh_token, expirationToken: 0 };
                        var date = new Date();
                        date.setTime(new Date().getTime() + (7 * 24 * 60 * 60 * 1000));
                        refreshToken.expirationToken = date.getTime();
                        localStorage.setItem('sust_refresh_token', JSON.stringify(refreshToken));

                        window.setTimeout(() => {

                            // redirect to login if the refresh token failed
                            ctx.AuthenticationService.refreshToken()['catch'](() => {
                                ctx.staticObjects.redirectToLogin();
                            });

                        }, (authData.expires_in - 5) * 1000);
                    }
                })
                .error((data, status: number, headers: (headerName: string) => string, config: ng.IRequestConfig) => {

                    localStorage.removeItem('sust_refresh_token');
                    localStorage.removeItem('sust:a:ur');
                    ctx.staticObjects.clearUserInfo();

                    if (data != undefined && data.error === "login_error_code") {
                        var code = parseInt(data.error_description);
                        ctx.usercredentials.errorMessage = ctx.staticObjects.getErrorMesageByStatusCode(500, { code: code });

                        if (code == 1007)
                            ctx.staticObjects.redirectToLink('/passwordExpired');

                        if (code == 1004)
                            ctx.staticObjects.redirectToDefault(ctx.redirectTo);
                    }
                    else {
                        ctx.usercredentials.errorMessage = data.error_description;
                    }
                });
        }

        private reevaluateCredentials(resetMessage) {
            var ctx = this;

            if (ctx.$$autocomplete) {

                var email = ctx.$$autocomplete.getEmail();
                if (ctx.usercredentials.username || email) {
                    if (ctx.usercredentials.username !== email) {
                        ctx.usercredentials.autoComplete = (ctx.usercredentials.autoComplete || 0) + 1;
                        ctx.usercredentials.username = email;
                        if (resetMessage) {
                            ctx.usercredentials.errorMessage = "";
                        }
                    }
                }

                var password = ctx.$$autocomplete.getPassword();
                if (ctx.usercredentials.password || password) {
                    if (ctx.usercredentials.password !== password) {
                        ctx.usercredentials.autoComplete = (ctx.usercredentials.autoComplete || 0) + 1;
                        ctx.usercredentials.password = password;
                        if (resetMessage) {
                            ctx.usercredentials.errorMessage = "";
                        }
                    }
                }

            }
        }

        private login() {
            var ctx = this;

            ctx.usercredentials.errorMessage = "";
            ctx.reevaluateCredentials(false);

            var emailRegularExpression = /\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
            var emailTest = emailRegularExpression.test(ctx.usercredentials.username);

            if (!emailTest) {
                ctx.usercredentials.errorMessage = "Please enter a valid email address.";
                return;
            }

            ctx.usercredentials.errorMessage = "";

            var loginParams = "grant_type=password" +
                "&username=" + ctx.usercredentials.username +
                "&password=" + ctx.usercredentials.password +
                "&client_id=clientId1" +
                "&client_secret=secret1";

            ctx.AuthenticationService.login(loginParams)
                .success((authData: AuthData) => {
                    if (!authData.access_token || !authData.expires_in || !authData.refresh_token) {
                        ctx.notificationFactory.error("", "Login failed!");
                    }
                    else {
                        ctx.usercredentials.errorMessage = "";
                        authData.loginTime = new Date();
                        ctx.$rootScope.authData = authData;
                        var refreshToken = { refreshToken: authData.refresh_token, expirationToken: 0 };

                        if (ctx.usercredentials.rememberMe) {
                            var date = new Date();
                            date.setTime(new Date().getTime() + (7 * 24 * 60 * 60 * 1000));
                            refreshToken.expirationToken = date.getTime();
                        }

                        localStorage.setItem('sust_refresh_token', JSON.stringify(refreshToken));

                        window.setTimeout(() => {

                            // redirect to login if the refresh token failed
                            ctx.AuthenticationService.refreshToken()['catch'](() => {
                                ctx.staticObjects.redirectToLogin();
                            });

                        }, (authData.expires_in - 5) * 1000);
                        
                        $.when(ctx.AuthenticationService.profile()
                            .success((userInfo: Common.IUserInfo) => {

                                //localStorage.setItem('sust_userInfo', JSON.stringify(userInfo));
                                ctx.UserInfoService.setUserInfo(userInfo);

                                ctx.$rootScope.userInfo = userInfo;

                                //ctx.$timeout(function () {
                                //    ctx.$rootScope.$apply(function () {
                                //        ctx.$rootScope.userInfo = userInfo;
                                //    });
                                //});           

                                // get ui resources
                                ctx.AuthenticationService.permissions()
                                    .success(() => {
                                    // after permissions have been fetched redirect to default page
                                    ctx.staticObjects.redirectToDefault(ctx.redirectTo);
                                });

                                //if (userInfo.isAuthenticated)
                                //staticObjects.initSignalR();

                                ga('create', 'UA-4379897-6', {
                                    'userId': ctx.$rootScope.userInfo.userId, 'cookieDomain': 'none', 'name': 'globalAccess'
                                });

                                ga('globalAccess.send', 'pageview'); 
                            })
                            .error(() => {
                                ctx.staticObjects.errorCallback.apply(ctx.staticObjects, arguments);
                            })
                            ); //ss


                    }
                })
                .error((data, status, headers, config) => {

                    if (data != undefined && data['error'] == "login_error_code") {
                        ctx.usercredentials.errorMessage = ctx.staticObjects.getErrorMesageByStatusCode(500, { code: parseInt(data['error_description']) });
                    }
                    else {
                        ctx.usercredentials.errorMessage = data['error_description'];
                    }
                    //notificationFactory.error("", "Login failed!");
                });
        }

        private forgotPassword() {

            var ctx = this;

            var emailRegularExpression = /\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
            var emailTest = emailRegularExpression.test(ctx.usercredentials.forgotPasswordEmail);

            if (!emailTest) {
                ctx.usercredentials.errorMessage = "Please enter a valid email address.";
                return;
            }

            ctx.AuthenticationService.forgotPassword('"' + ctx.usercredentials.forgotPasswordEmail + '"')
                .success(() => {
                    ctx.usercredentials.errorMessage = "";
                    ctx.staticObjects.redirectToLink("/forgotPasswordConfirmation");
                })
                .error((data, status, headers, config) => {
                    ctx.usercredentials.errorMessage = ctx.staticObjects.getErrorMesageByStatusCode(status, data);
                });
        }

        private changePassword() {
            var ctx = this;

            var changePassword: ChangePassword = { username: ctx.usercredentials.username, password: ctx.usercredentials.password };

            ctx.AuthenticationService.changePassword(changePassword)
                .success(() => {
                    ctx.usercredentials.errorMessage = "";
                    $.when(ctx.AuthenticationService.profile()
                        .success((userInfo: Common.IUserInfo) => {

                            ctx.$rootScope.userInfo = userInfo;

                            //ctx.$timeout(function () {
                            //    ctx.$rootScope.$apply(function () {
                            //        ctx.$rootScope.userInfo = userInfo;
                            //    });
                            //});
                        })
                        .error(function () {
                            ctx.staticObjects.errorCallback.apply(ctx.staticObjects, arguments);
                        })
                        )
                        .done(() => {
                            ctx.staticObjects.redirectToDefault(ctx.redirectTo);
                        });
                })
                .error((data, status, headers, config) => {
                    ctx.usercredentials.errorMessage = ctx.staticObjects.getErrorMesageByStatusCode(status, data);
                });
        }

        private minimumLength() {
            var ctx = this;

            this.$scope.changePasswordForm.passwordBox.$setValidity("PasswordLength", ctx.usercredentials.password.length > 6);

            return ctx.usercredentials.password.length > 6;
        }

        private hasCapital() {
            var ctx = this;

            var regexp = /(?=.*[A-Z])/;

            this.$scope.changePasswordForm.passwordBox.$setValidity("PasswordDoesNotHaveCapital", regexp.test(ctx.usercredentials.password));

            return regexp.test(ctx.usercredentials.password);
        }

        private hasNumber() {
            var ctx = this;

            var regexp = /(?=.*[0-9])/;
            this.$scope.changePasswordForm.passwordBox.$setValidity("PasswordDoesNotHaveNumber", regexp.test(ctx.usercredentials.password));

            return regexp.test(ctx.usercredentials.password);
        }

        private passwordMatch() {
            var ctx = this;

            this.$scope.changePasswordForm.passwordBox.$setValidity("PasswordDoesNotMatch", ctx.usercredentials.password == ctx.usercredentials.confirmPassword);
            return ctx.usercredentials.password == ctx.usercredentials.confirmPassword && ctx.usercredentials.password.length > 0
        }

        private invalidCharacters() {
            var ctx = this;

            var regexp = /(^.*?(?=[&'"<>}]).*$)/;
            this.$scope.changePasswordForm.passwordBox.$setValidity("PasswordHasInvalidCharacter", !regexp.test(ctx.usercredentials.password));

            return regexp.test(ctx.usercredentials.password);
        }

        private activateSignalR() {
            var ctx = this;

            $.connection.hub.start()
                .done(() => {
                })
                .fail(error => {
                    alert(error.message);
                });
        }
    }

    export var accountControllerName = 'AccountController';

    angular.module(authenticationModuleName).controller(accountControllerName, AccountController);
}